package app.services;

import app.Const;
import app.kit.CommonKit;
import app.kit.TypeKit;
import app.models.order.AccountAmount;
import app.models.order.CheckAccount;
import app.models.order.Order;
import bank.BankService;
import bank.resp.AccountAmountRspDto;
import bank.resp.OrderInfoRspDto;
import bank.resp.ReconciliationDto;
import bank.resp.ReconciliationItemDto;
import bank.resp.ReconciliationOverallDto;
import com.google.common.base.Optional;
import goja.Logger;
import goja.StringPool;
import goja.date.DateFormatter;
import goja.plugins.sqlinxml.SqlKit;
import org.joda.time.DateTime;

import java.math.BigDecimal;
import java.util.List;

/**
 * <p> 对账服务 </p>
 *
 * @author sogYF
 * @version 1.0
 * @since JDK 1.6
 */
public class CheckAccountService {
    /**
     * 如果要调用该单例的使用,只能通过该方法获取.
     */
    public static final CheckAccountService me = new CheckAccountService();

    /**
     * 私有构造函数,确保对象只能通过单例方法来调用.
     */
    private CheckAccountService() {
    }

    /**
     * 对账服务
     *
     * @param start_time 开始时间
     * @param end_time   结束时间
     */
    public void checkAccount(DateTime start_time, DateTime end_time) {
        boolean run_page = true;
        int page = 1;
        ReconciliationDto reconciliationDto;
        ReconciliationOverallDto overallDto;
        List<ReconciliationItemDto> items;
        while (run_page) {
            DateTime now = DateTime.now();
            final Optional<ReconciliationDto> checkAccount_opt =
                    BankService.me.checkAccount(now, now, start_time, end_time, page, 120);
            if (checkAccount_opt.isPresent()) {
                reconciliationDto = checkAccount_opt.get();
                overallDto = reconciliationDto.getOverallDto();
                if (overallDto.getTotalPages() == 0) {
                    return;
                }
                items = reconciliationDto.getItems();
                CheckAccount.dao.record(items, now);
                // 如果为true，则继续获取
                run_page = overallDto.isHasNext();
                page++;
            }
        }
    }


    public void checkAmount() {
        DateTime now = DateTime.now();
        Optional<AccountAmountRspDto> merchantAccntAmount = BankService.me.getMerchantAccntAmount(now, now);
        if (merchantAccntAmount.isPresent()) {
            AccountAmountRspDto amountRspDto = merchantAccntAmount.get();
            if (amountRspDto.isSuccess()) {
                String partnerId = amountRspDto.getPartnerId();
                AccountAmount day = AccountAmount.dao.findByDate(now);
                if (day == null) {
                    day = new AccountAmount();
                    day.set(StringPool.PK_COLUMN, CommonKit.uuid());
                    day.set("day", now);
                    day.set("balance", amountRspDto.getTotalBalance());
                    day.set("available", amountRspDto.getAvailableBalance());
                    day.set("freeze", amountRspDto.getFreezeBalance());
                    day.set("last_day", amountRspDto.getLastDayBalance());
                    day.set("account", partnerId);
                    day.save();
                } else {

                    day.set("day", now);
                    day.set("balance", amountRspDto.getTotalBalance());
                    day.set("available", amountRspDto.getAvailableBalance());
                    day.set("freeze", amountRspDto.getFreezeBalance());
                    day.set("last_day", amountRspDto.getLastDayBalance());
                    day.set("account", partnerId);
                    day.update();
                }
            }

        }
    }

    /**
     * 对某条对账纪录重新纪录
     *
     * @param order           平台订单信息
     * @param orderInfoRspDto 银行返回信息
     */
    public void checkAccount(Order order, OrderInfoRspDto orderInfoRspDto) {
        String findByInnerOrderno = SqlKit.sql("checkaccount.findByInnerOrderNo");

//        String orderNo;

        int outcome;
        String exp = Const.NO;
        String innerOrderNo = orderInfoRspDto.getInnerOrderNo();
//        orderNo = orderInfoRspDto.getOuterOrderNo();
        CheckAccount checkAccountRecord = CheckAccount.dao.findFirst(findByInnerOrderno, innerOrderNo);
        if(checkAccountRecord == null){
            Logger.info("check_account record is not generate, ignore", innerOrderNo);
            return;
        }
        BigDecimal outerOrderAmount;

        // 1 表示一致账单
        outcome = CheckAccount.OK_OUT;
        int outerOrderStatus = TypeKit.getStatus(order);
        if (outerOrderStatus != orderInfoRspDto.getOrderStatus()) {
            // 订单状态不一致
            exp = Const.YES;
            // 1 表示账单状态问题
            outcome = CheckAccount.STASUS_OUT;
        }
        outerOrderAmount = order.getBigDecimal("trade_amount");
        if (outerOrderAmount.compareTo(orderInfoRspDto.getAmount()) != 0) {
            // 4 订单金额不一致
            exp = Const.YES;
            outcome = CheckAccount.AMOUNT_OUT;
        }
        checkAccountRecord.set("transdate", orderInfoRspDto.getCreateTime().toString(DateFormatter.YYYYMMDD));
        checkAccountRecord.set("reqbizdate", orderInfoRspDto.getRespBizDate());
        checkAccountRecord.set("outerorderno", orderInfoRspDto.getOuterOrderNo());
        checkAccountRecord.set("innerorderno", orderInfoRspDto.getInnerOrderNo());
        checkAccountRecord.set("orderstatus", orderInfoRspDto.getOrderStatus());
        checkAccountRecord.set("ordertype", orderInfoRspDto.getOrderType());
        checkAccountRecord.set("amount", orderInfoRspDto.getAmount());
        checkAccountRecord.set("fee", orderInfoRspDto.getFee());
        checkAccountRecord.set("currency", orderInfoRspDto.getCurrency());
        checkAccountRecord.set("check_time", DateTime.now());
        checkAccountRecord.set("exp_flag", exp);
        checkAccountRecord.set("outcome", outcome);
        checkAccountRecord.set("outerorderstatus", outerOrderStatus);
        checkAccountRecord.set("outerorderamount", outerOrderAmount);
        checkAccountRecord.update();

        Logger.info("the check account of orderno is {}", orderInfoRspDto.getOuterOrderNo());
    }
}
